package com.itany.corejava.code08_常用类.string类;

/**
 * @author 石小俊
 * 2024年07月22日 10:40
 */
public class Test08_常量池 {

    public static void main(String[] args) {
        // 此时表示在堆中开辟了一块内存区域,用于存储数据admin
        String s = new String("admin");
        // 此时在堆中又重新开辟了一块内存区域,用于存储数据alice
        s = new String("alice");

        // 此时没有指向已有的内存区域,而是重新开辟了一块内存区域
        String s2 = new String("admin");

        // 通过双引号创建的字符串表示字符常量,是存储在常量池中的
        // 在常量池中开辟了一块内存区域,用于存储数据admin
        String s3 = "admin";
        // 在常量池中重新开辟了一块内存区域,用于存储alice
        s3 = "alice";

        // 此时由于已经存在存储admin数据的内存区域了
        // 因此,此时没有开辟新的区域,而是直接指向了已有的区域
        String s4 = "admin";

        String s5 = new String("admin");
        // 由于s2与s5并不是同一个内存区域,存储在栈中的地址是不一样的,返回false
        System.out.println(s2 == s5);   // false

        String s6 = "admin";
        // 由于s4与s6是存储在常量池中的,且值是同一个,因此指向了同一个区域,返回true
        System.out.println(s4 == s6);   // true

        String s7 = "a";
        String s8 = "aa";
        String s9 = "aaa";
        String s10 = s7 + s8;   // aaa
        // 当变量的值是经过运算得到的时候
        // 如果运算过程中涉及的所有值都是常量,则存储到常量池中
        // 如果运算过程中涉及的值存在变量,则存储到堆中
        // s10的运算过程中涉及的是变量,因此其值存储在堆中
        // 此时s9存储在常量池,s10存储在堆中,返回false
        System.out.println(s9 == s10);  // false-
        // s11在运算过程中涉及的所有成员都是常量,因此直接存储在常量池中
        // 由于常量池中已经存在aaa的数据了,则直接指向已有的地址,因此返回true
        String s11 = "a" + "aa";  // aaa
        System.out.println(s9 == s11);  // true

        String s12 = "a" + s8;
        System.out.println(s9 == s12);

        // 堆中6个对象,常量池5个对象

    }

}
